package cn.wolfcode.web.controller;

import cn.wolfcode.common.constants.CommonConstants;
import cn.wolfcode.common.domain.UserInfo;
import cn.wolfcode.common.exception.BusinessException;
import cn.wolfcode.common.web.CommonCodeMsg;
import cn.wolfcode.common.web.Result;
import cn.wolfcode.common.web.anno.RequireLogin;
import cn.wolfcode.domain.SeckillProductVo;
import cn.wolfcode.mq.MQConstant;
import cn.wolfcode.mq.OrderMessage;
import cn.wolfcode.redis.SeckillRedisKey;
import cn.wolfcode.service.IOrderInfoService;
import cn.wolfcode.service.ISeckillProductService;
import cn.wolfcode.util.DateUtil;
import cn.wolfcode.util.UserUtil;
import cn.wolfcode.web.msg.SeckillCodeMsg;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;


@RestController
@RequestMapping("/order")
@Slf4j
public class OrderInfoController {
    @Autowired
    private ISeckillProductService seckillProductService;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Autowired
    private IOrderInfoService orderInfoService;

    private final Map<Long,Boolean> STOCK_OVER_FLAG_MAP = new ConcurrentHashMap<>();


    @RequireLogin
    @RequestMapping("/doSeckill")
    public Result<String> doSeckill(@RequestHeader(CommonConstants.TOKEN_NAME) String token, Long seckillId, Integer time) {
        //判断是否登录
        //判断参数是否合法
        if(seckillId==null || time == null) {
            throw new BusinessException(CommonCodeMsg.ILLEGAL_OPERATION);
        }
        Boolean aBoolean = STOCK_OVER_FLAG_MAP.get(seckillId);
        if(aBoolean!=null && aBoolean) {
            throw new BusinessException(SeckillCodeMsg.SECKILL_STOCK_OVER);
        }

        //根据id和time查询商品，查不到说明传的参数有误
        SeckillProductVo seckillProductVo = seckillProductService.find(time, seckillId);
        if(seckillProductVo==null) {
            throw new BusinessException(CommonCodeMsg.ILLEGAL_OPERATION);
        }
        //判断是否在秒杀时间内
//        boolean legalTime = DateUtil.isLegalTime(seckillProductVo.getStartDate(), time);
//        if(!legalTime) {
//            throw new BusinessException(SeckillCodeMsg.INTERGRAL_TIME_ERROR);
//        }
        //判断库存是否足够
//        if(seckillProductVo.getStockCount()<=0) {
//            throw new BusinessException(SeckillCodeMsg.SECKILL_STOCK_OVER);
//        }
        String stockCountHashRealKey = SeckillRedisKey.SECKILL_STOCK_COUNT_HASH.getRealKey(time + "");
        Long increment = redisTemplate.opsForHash().increment(stockCountHashRealKey,
                seckillProductVo.getId() + "",
                -1);
        if(increment<0) {
            //存入map防止没库存了还继续访问redis
            STOCK_OVER_FLAG_MAP.put(seckillId,true);
            throw new BusinessException(SeckillCodeMsg.SECKILL_STOCK_OVER);
        }
        UserInfo user = UserUtil.getUser(redisTemplate, token);
        //判断用户是否重复下单
//        String realKey = SeckillRedisKey.SECKILL_ORDER_SET.getRealKey(time + "");
//        Boolean member = redisTemplate.opsForSet().isMember(realKey, user.getPhone() + ":" + seckillId );
        String realKey = SeckillRedisKey.SECKILL_ORDER_HASH.getRealKey(time + "");
        Boolean absent = redisTemplate.opsForHash().putIfAbsent(realKey, user.getPhone() + ":" + seckillId, "1");
        if(!absent) {
            throw new BusinessException(SeckillCodeMsg.REPEAT_SECKILL);
        }
        //秒杀
//        String oderNum = orderInfoService.doSeckill(seckillProductVo,user);
        OrderMessage message = new OrderMessage(time,seckillId,token,user.getPhone());
        rocketMQTemplate.asyncSend(MQConstant.ORDER_PENDING_TOPIC, message, new SendCallback() {
            @Override
            public void onSuccess(SendResult sendResult) {
                log.info("[秒杀下单] 发送消息成功：status={},messageId={}",sendResult.getSendStatus(),sendResult.getMsgId());
            }

            @Override
            public void onException(Throwable throwable) {
                log.error("[秒杀下单] 发送消息失败：",throwable);
            }
        });
        return Result.success("正在下单中，请稍后");
    }
}
